/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.thienloc.omap.controller;

//import com.thienloc.omap.entity.OmapUser;
import com.thienloc.omap.entity.OmapResource;
import com.thienloc.omap.entity.OmapRole;
import com.thienloc.omap.entity.OmapUser;
import com.thienloc.omap.entity.Permission;
import com.thienloc.omap.entity.UserCmdCode;
import com.thienloc.omap.session.OmapUserFacade;
import com.thienloc.omap.session.UserCmdCodeFacade;
import com.thienloc.omap.util.JsfUtil;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;
import javax.annotation.PostConstruct;
import javax.ejb.EJB;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ManagedProperty;
import javax.faces.bean.SessionScoped;
import javax.faces.context.FacesContext;
import javax.servlet.http.HttpSession;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 *
 * @author GiangLT
 */
@ManagedBean(name = "sessionBean")
@SessionScoped
public class SessionBean implements Serializable {

    @EJB
    private OmapUserFacade omapUserFacade;
    @EJB
    private UserCmdCodeFacade userCmdCodeFacade;
    @ManagedProperty(value = "#{applicationBean}")
    private ApplicationBean applicationBean;
    private String currentLanguage = "vi_VN";
    private OmapUser omapUser;
    private boolean loggedIn = false;
    private int loginFailCount;
    private AtomicInteger broadcastInstantSeq = new AtomicInteger(1);
    private List<Permission> permissions;
    private Map<String, String> blackCmdCodeMap;
    private Map<String, String> whiteCmdCodeMap;
    private final Logger logger = LoggerFactory.getLogger(SessionBean.class);

    /**
     * Creates a new instance of SessionBean
     */
    public SessionBean() {
    }

    @PostConstruct
    public void init() {
        omapUser = new OmapUser();
        loginFailCount = 0;
    }

    public String logout() {
        try {
            applicationBean.removeLoggedInUser(omapUser.getUsername());
            logger.debug("[{}] User logged out", omapUser.getUsername());
            omapUser = new OmapUser();
            permissions = null;
            loginFailCount = 0;
            loggedIn = false;
            FacesContext facesContext = FacesContext.getCurrentInstance();
            HttpSession session = (HttpSession) facesContext.getExternalContext().getSession(false);
            session.removeAttribute("user");
            return "login?faces-redirect=true";
        } catch (Exception e) {
            JsfUtil.addErrorMessage("Đăng xuất thất bại", e.getMessage());
            return null;
        }
    }

    public String login() {
        try {
            OmapUser user = omapUserFacade.findByUsernameAndPassword(omapUser.getUsername(), omapUser.getPassword());
            if (user != null) {
//                if (user.getTrustedIps() != null && !user.getTrustedIps().trim().isEmpty()) {
//                    Iterable<String> iTrustedIps = Splitter.on(',').trimResults().split(user.getTrustedIps());
//                    List<String> trustedIps = Lists.newArrayList(iTrustedIps);
//                    if (trustedIps != null && !trustedIps.isEmpty()) {
//                        String clientIp = JsfUtil.getClientIp();
//                        if (!trustedIps.contains(clientIp)) {
//                            loginFailCount++;
//                            JsfUtil.addErrorMessage("Đăng nhập thất bại", "IP của máy này không được phép đăng nhập với user " + user.getUsername());
//                            return "";
//                        }
//                    }
//                }
//                if (applicationBean.isUserLoggedIn(user.getUsername())) {
//                    JsfUtil.addErrorMessage("Đã đăng nhập", "Tài khoản này đã đăng nhập từ máy khác");
//                    return "";
//                }
                applicationBean.addLoggedInUser(user);

                omapUser = user;
                loggedIn = true;
                loginFailCount = 0;

                FacesContext facesContext = FacesContext.getCurrentInstance();
                HttpSession session = (HttpSession) facesContext.getExternalContext().getSession(false);
                session.setAttribute("user", omapUser);

                logger.debug("[{}] User logged in", omapUser.getUsername());
                omapUser.setLastLoginDate(new Date());
                omapUserFacade.edit(omapUser);
                loadPermissions();
                try {
                    loadUserCmdCodes();
                } catch (Exception ex) {
                    logger.error("[{}] Error loading userCommandCodes", omapUser.getUsername(), ex);
                }

                return "index?faces-redirect=true";
            } else {
                loginFailCount++;
                JsfUtil.addErrorMessage("Đăng nhập thất bại", "Sai tên đăng nhập hoặc mật khẩu");
                return "";
            }
        } catch (Exception e) {
            JsfUtil.addErrorMessage("Đăng nhập thất bại", e.getMessage());
            return "";
        }
    }

    public boolean hasRight(String resourceName, String action) {
        for (Permission permission : permissions) {
            if (permission.getResourceId().getName().equals(resourceName)
                    && permission.getAction().equals(action)) {
                return true;
            }
        }
        return false;
    }

    public List<String> getPermissions() {
        List<String> result = new ArrayList<String>(permissions.size());

        for (Permission permission : permissions) {
            result.add(permission.getResourceId().getName() + " - " + permission.getAction());
        }
        return result;
    }

    public void addPermission(String resourceName, String action) {
        OmapResource resource = new OmapResource();
        resource.setName(resourceName);
        Permission permission = new Permission();
        permission.setResourceId(resource);
        permission.setAction(action);

        permissions.add(permission);
    }

    public void authenticate() {
        if (!loggedIn) {
            FacesContext facesContext = FacesContext.getCurrentInstance();
            JsfUtil.redirectPage(facesContext, "faces/login.xhtml");
        }
    }

    public int getBroadcastInstantSeq() {
        int seq = broadcastInstantSeq.get();
        if (seq == Integer.MAX_VALUE) {
            broadcastInstantSeq.set(0);
        } else {
            broadcastInstantSeq.incrementAndGet();
        }
        return seq;
    }

    public void setBroadcastInstantSeq(AtomicInteger broadcastInstantSeq) {
        this.broadcastInstantSeq = broadcastInstantSeq;
    }

    //<editor-fold defaultstate="collapsed" desc="Setters & Getters">
    public String getUserIp() {
        return JsfUtil.getClientIp();
    }

    public String getCurrentLanguage() {
        return currentLanguage;
    }

    public void setCurrentLanguage(String currentLanguage) {
        this.currentLanguage = currentLanguage;
    }

    public boolean isLoggedIn() {
        return loggedIn;
    }

    public void setLoggedIn(boolean loggedIn) {
        this.loggedIn = loggedIn;
    }

    public int getLoginFailCount() {
        return loginFailCount;
    }

    public void setLoginFailCount(int loginFailCount) {
        this.loginFailCount = loginFailCount;
    }

    public OmapUser getOmapUser() {
        return omapUser;
    }

    public void setOmapUser(OmapUser omapUser) {
        this.omapUser = omapUser;
    }

    //</editor-fold>
    public ApplicationBean getApplicationBean() {
        return applicationBean;
    }

    public void setApplicationBean(ApplicationBean applicationBean) {
        this.applicationBean = applicationBean;
    }

    private void loadPermissions() {
        permissions = omapUser.getPermissionList();
        List<OmapRole> roles = omapUser.getOmapRoleList();
        for (OmapRole omapRole : roles) {
            List<Permission> rolePermissions = omapRole.getPermissionList();
            for (Permission rolePermission : rolePermissions) {
                boolean found = false;
                for (Permission userPermission : permissions) {
                    if (rolePermission.getAction().equals(userPermission.getAction())
                            && rolePermission.getResourceId().getName().equals(userPermission.getResourceId().getName())) {
                        found = true;
                        break;
                    }
                }
                if (!found) {
                    permissions.add(rolePermission);
                }
            }
        }
    }

    private void loadUserCmdCodes() throws Exception {
        UserCmdCode userCmdCode = userCmdCodeFacade.findByUsername(omapUser.getUsername());

        String blackCmdList = userCmdCode.getBlackCmdList();
        if (blackCmdList != null) {
            String[] blackCmdCodes = blackCmdList.split(",");
            blackCmdCodeMap = new HashMap<String, String>(blackCmdCodes.length);
            for (String blackCmdCode : blackCmdCodes) {
                blackCmdCodeMap.put(blackCmdCode, blackCmdCode);
            }
        }

        String whiteCmdList = userCmdCode.getWhiteCmdList();
        if (whiteCmdList != null) {
            String[] whiteCmdCodes = whiteCmdList.split(",");
            whiteCmdCodeMap = new HashMap<String, String>(whiteCmdCodes.length);
            for (String whiteCmdCode : whiteCmdCodes) {
                whiteCmdCodeMap.put(whiteCmdCode, whiteCmdCode);
            }
        }
    }
}
